"""Custom exception classes for AI service."""

from typing import Optional, Dict, Any


class AIServiceError(Exception):
    """Base exception for AI service errors."""
    
    def __init__(
        self,
        message: str,
        error_code: Optional[str] = None,
        details: Optional[Dict[str, Any]] = None
    ):
        """Initialize AI service error.
        
        Args:
            message: Error message
            error_code: Optional error code
            details: Optional error details
        """
        super().__init__(message)
        self.message = message
        self.error_code = error_code or "AI_SERVICE_ERROR"
        self.details = details or {}
    
    def to_dict(self) -> Dict[str, Any]:
        """Convert error to dictionary.
        
        Returns:
            Error as dictionary
        """
        return {
            "error": self.error_code,
            "message": self.message,
            "details": self.details
        }


class ModelError(AIServiceError):
    """Error related to model operations."""
    
    def __init__(
        self,
        message: str,
        model_name: Optional[str] = None,
        details: Optional[Dict[str, Any]] = None
    ):
        """Initialize model error.
        
        Args:
            message: Error message
            model_name: Name of the model
            details: Optional error details
        """
        super().__init__(message, "MODEL_ERROR", details)
        self.model_name = model_name
        if model_name:
            self.details["model"] = model_name


class RateLimitError(AIServiceError):
    """Error when rate limit is exceeded."""
    
    def __init__(
        self,
        message: str,
        retry_after: Optional[int] = None,
        details: Optional[Dict[str, Any]] = None
    ):
        """Initialize rate limit error.
        
        Args:
            message: Error message
            retry_after: Seconds to wait before retry
            details: Optional error details
        """
        super().__init__(message, "RATE_LIMIT_ERROR", details)
        self.retry_after = retry_after
        if retry_after:
            self.details["retry_after"] = retry_after


class TimeoutError(AIServiceError):
    """Error when operation times out."""
    
    def __init__(
        self,
        message: str,
        timeout: Optional[float] = None,
        details: Optional[Dict[str, Any]] = None
    ):
        """Initialize timeout error.
        
        Args:
            message: Error message
            timeout: Timeout duration in seconds
            details: Optional error details
        """
        super().__init__(message, "TIMEOUT_ERROR", details)
        self.timeout = timeout
        if timeout:
            self.details["timeout"] = timeout


class InvalidRequestError(AIServiceError):
    """Error for invalid requests."""
    
    def __init__(
        self,
        message: str,
        field: Optional[str] = None,
        details: Optional[Dict[str, Any]] = None
    ):
        """Initialize invalid request error.
        
        Args:
            message: Error message
            field: Field that caused the error
            details: Optional error details
        """
        super().__init__(message, "INVALID_REQUEST", details)
        self.field = field
        if field:
            self.details["field"] = field


class ModelNotAvailableError(ModelError):
    """Error when requested model is not available."""
    
    def __init__(
        self,
        model_name: str,
        available_models: Optional[list] = None
    ):
        """Initialize model not available error.
        
        Args:
            model_name: Name of the unavailable model
            available_models: List of available models
        """
        message = f"Model '{model_name}' is not available"
        details = {}
        if available_models:
            details["available_models"] = available_models
            message += f". Available models: {', '.join(available_models)}"
        
        super().__init__(message, model_name, details)
        self.available_models = available_models